package com.m4f.fse.components.fitters.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import com.m4f.fse.components.fitters.ifc.Fitter;
import com.m4f.fse.model.Container;
import com.m4f.fse.model.Metadata;
import com.m4f.fse.model.Query;
import com.m4f.fse.model.Result;

public class GsaFitter implements Fitter {
	
	
	@SuppressWarnings("unchecked")
	@Override
	public ByteArrayOutputStream fit(Query query,
			Map<String, String> params) throws Exception {
		/*Default initilisation*/
		int start = 0, num = 10;
		try {
			start = Integer.parseInt(params.get("start"));
		} catch(Exception e) {
			
		}
		try {
			num = Integer.parseInt(params.get("num"));
		} catch(Exception e) {
			
		}
		
		Document doc = ((Container<Document>) query.getContainer()).get();
		for (Iterator<Element> it = doc.getRootElement().getChildren("PARAM").iterator(); it.hasNext(); ) {
			Element param = it.next();
			if(param.getAttributeValue("name").equals("num")){
				param.setAttribute("value", "" + num);
				param.setAttribute("original_value", "" + num);
			}
			if(param.getAttributeValue("name").equals("start")){
				param.setAttribute("value", "" + start);
				param.setAttribute("original_value", "" + start);
			}
		}

		if(query.getResults().size() > 0 && 
				(start < query.getResults().size())) {
			List<Result> cutted = this.cutResults(query, 
					start, num);
			this.buildResultsFragment(doc, cutted, query, 
					start, num);
		}
		return this.dumpContent(doc);
	}
	
	
	@SuppressWarnings("unchecked")
	private List<Result> cutResults(Query query, int start, int num) {
		List<Result> cutted = new ArrayList<Result>();
		cutted.addAll(query.getResults());
		int totalResults = query.getResults().size();
		int end = num+start;
		if(start == totalResults) {
			start = (int) totalResults - 1;
		}
		if(end > totalResults) {
			end = (int) totalResults;
		}
		cutted = cutted.subList(start, end); 
		return cutted;
	}
	
	
	 
	@SuppressWarnings("unchecked")
	private void buildResultsFragment(Document doc, List<Result> eles, 
				Query query, int start, int num) {	
			Element resultsEl = new Element("RES");	
			resultsEl.setAttribute("SN",  (start + 1) + "");
			resultsEl.setAttribute("EN", (eles.size() + start) + "");
			Element totalResults = new Element("M");
			resultsEl.addContent(totalResults);
			totalResults.addContent("" + query.getResults().size());
			for (Iterator<Metadata<?>> it = query.getResultMetaInformation().iterator(); it.hasNext(); ) {
				Metadata<Element> metadata = (Metadata<Element>)it.next();
				resultsEl.addContent(metadata.get());
			}
			for (Iterator<Result> it = eles.iterator(); it.hasNext(); ) {
				Result<Element> result = (Result<Element>)it.next();
				resultsEl.addContent(result.get());
			
			}
			doc.getRootElement().addContent(resultsEl);
	}
	
	
	 
	private ByteArrayOutputStream dumpContent(Document doc) throws IOException {
		XMLOutputter outp = new XMLOutputter();
		outp.setFormat(Format.getPrettyFormat().setEncoding("ISO-8859-1"));
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		outp.output(doc, bos);
		return bos;
	}
	
}
